/* NOTICE
 
    Jim - the Java Image Manager, copyright (c) 2005 - 2007 Grant Gardner 
 
    Jim is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Jim is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    In addition, as a special exception, you are permitted to link this code
    with the 3rd party libraries required to compile this file and to
    distribute a linked combination including them. You must obey the
    GNU General Public License in all respects for all of the code except for
    those 3rd party libraries that are licenced under terms incompatible with the
    GNU General Public License.  
 
 
 NOTICE */

/*
 * Created on 27/07/2004
 *
 */

package au.com.lastweekend.jim.io.jpeg;

/**
 * Static helper methods for Jpeg bitwise operations. Because I'm abnormally paranoid about the number of times these routines are
 * being called, everything is done with 32 bit (int) precision A final cast to byte or short should include a bitwise and (&) with
 * 0xFF or 0xFFFF respectively.
 * 
 * 
 * @version $Id: JpegBitOps.java,v 1.3 2006/01/28 05:05:40 ggardner Exp $
 * @author grant@lastweekend.com.au
 * 
 */
public final class JpegBitOps {

    private JpegBitOps() {

        throw new UnsupportedOperationException();
    }

    /**
     * 
     * 
     * See Jpeg spec figure F.12 <br>
     * <code>
     * 0            = (0) 
     * -1. 1        = (1) 0. 1 
     * -3 -2 . 2 3  = (2) 00 01 . 10 11 
     * -7..-4.4..7  = (3) 000 001 010 011 . 00000100 00000101 00000110 00000111
     * </code>
     * To convert
     * 
     * @param value
     *            The coded bits
     * @param bits
     *            The number of coded bits
     * @return as per code above
     */
    public static int extend(int value, int bits) {

        if (bits == 0) {
            return 0;
        }

        if (value < (1 << (bits - 1))) {
            // Value represents a negative number.
            // Shift -1 to the left by additional bits then add value + 1;
            value = ((-1 << bits) + value + 1);
        }

        return value;
    }

    /**
     * See Jpeg spec table F1/F2. This code gets the category from the value
     * 
     * @param value
     *            0 <= bits <= 16
     * @return category from value
     */
    public static int getCategorySize(int value) {

        if (value < 0) {
            value = -value;
        }
        // Number of bits to encode absolute value
        // value < 2 ^ (bits)
        // 0 .. (0) 1 > 0 ...
        // -1 - 1 .. (0) 1 <= 1 , (1) 2 > 1
        // -2 - 2 .. (0) 1 <= 2, (1) 2 <= 2, (2) 4 > 2
        // -3 - 3... (0) 1 <= 3 (1) (2 <= 3), (2) ( 4 > 3)
        int bits = 0;
        while (bits < 11 && (0x01 << (bits)) <= value) {
            bits++;
        }
        return bits;
    }

    public static int getLow4Bits(byte value) {

        return (value & 0x0F);
    }

    public static int getHigh4Bits(byte value) {

        return ((value >> 4) & 0x0F);
    }
}